'''
# 作者    ： 张莹潇
# 创建时间 ： 20/12/2 15:06
'''
# encoding: UTF-8

import glob
import pandas as pd
import talib, time
import datetime
from tick_data_to_minbar import *
from CTPtools import *

class StrategyZyx(object):
    fixed_size = 1
    # record_list为成交记录
    record_list = pd.DataFrame(columns=('date', 'symbol', 'direction', 'price', 'size'))
    # pos_information为持仓情况
    pos_information = pd.DataFrame(columns=('symbol', 'pos'))

    # 空
    def sell(self, symbol, price, size, time):
        for i in range(len(self.pos_information)):
            if self.pos_information['symbol'][i] == symbol:
                self.pos_information['pos'][i] -= size

        new_record = pd.Series({'date': time, 'symbol': symbol, 'direction':'sell', 'price': price, 'size':size})
        # 这里 Series 必须是 dict-like 类型

        self.record_list = self.record_list.append(new_record, ignore_index=True)
        return self.record_list
    # 多
    def buy(self, symbol, price, size, time):
        for i in range(len(self.pos_information)):
            if self.pos_information['symbol'][i] == symbol:
                self.pos_information['pos'][i] += size

        new_record = pd.Series({'date': time, 'symbol': symbol, 'direction': 'buy', 'price': price, 'size': size})
        # 这里 Series 必须是 dict-like 类型
        self.record_list = self.record_list.append(new_record, ignore_index=True)
        return self.record_list

class TradingResult(object):
    """每笔交易的结果"""

    def __init__(self, variety, entryPrice, Dt, exitPrice, volume, rate, slippage, size):
        """Constructor"""
        self.slippage = 0  # 回测时假设的滑点
        self.rate = 0  # 回测时假设的佣金比例（适用于百分比佣金）
        self.size = 1  # 合约大小，默认为1

        self.variety = variety
        self.entryPrice = entryPrice  # 开仓价格
        self.exitPrice = exitPrice  # 平仓价格

        self.Dt = Dt  # 时间datetime

        self.volume = volume  # 交易数量（+/-代表方向）

        self.turnover = (self.entryPrice + self.exitPrice) * size * abs(volume)  # 成交金额
        self.commission = self.turnover * rate  # 手续费成本
        self.slippage = slippage * 2 * size * abs(volume)  # 滑点成本
        self.pnl = ((self.exitPrice - self.entryPrice) * volume * size
                    - self.commission - self.slippage)  # 净盈亏

if __name__ == '__main__':

    # Addr交易服务器地址
    FrontAddr = "tcp://218.202.237.33 :10102"
    # LoginInfo
    BROKERID = "9999"
    USERID = "171525"
    PASSWORD = "1234qwer@"
    AppID = "simnow_client_test"
    AuthCode = "0000000000000000"

    tradeapi = api.CThostFtdcTraderApi_CreateFtdcTraderApi()
    tradespi = CTradeSpi(tradeapi, BROKERID, USERID, PASSWORD, AppID, AuthCode)
    tradeapi.RegisterFront(FrontAddr)
    tradeapi.RegisterSpi(tradespi)
    tradeapi.SubscribePrivateTopic(api.THOST_TERT_QUICK)
    tradeapi.SubscribePublicTopic(api.THOST_TERT_QUICK)
    tradeapi.Init()
    time.sleep(10)
    ReqQryTradingAccountAndPosition(tradeapi, BROKERID, USERID)
    time.sleep(5)
    position_local = tradespi.position
    account_local = tradespi.account

    # OrderInfo
    EXCHANGEID = "CFFEX"
    INSTRUMENTID = "IF2012"
    VOLUME = 1
    # open开仓
    OFFSET="0"
    # close平仓
    # OFFSET = "1"
    OrderRef = 1

    Strategy = StrategyZyx()
    # file_list = glob.glob("future_data_hot/AG2012.XSGE.csv")
    # print(file_list)
    resultList = []  # 交易结果列表
    # for file in file_list:
    #     file_name = file.split("/")[1]
        # print(file_name)
    # account_list = pd.DataFrame(columns=('date', 'balance'))
    # new_account = pd.Series({'date': time, 'balance': account_local["balance"])
    # # 这里 Series 必须是 dict-like 类型
    #
    # account_list = account_list.append(new_account, ignore_index=True)
    while(True):
        if(int(time.time())%60 == 0):
            print("正分钟")
            position_local = tradespi.position
            account_local = tradespi.account
            if("CFFEX.IF2012" in position_local):
                pos = position_local["CFFEX.IF2012"]["pos"]
            else:
                pos = 0
            print("pos:",pos)
            symbol = "IF2012"
            s = pd.Series({'symbol': symbol, 'pos': 0})
            # 这里 Series 必须是 dict-like 类型
            Strategy.pos_information = Strategy.pos_information.append(s, ignore_index=True)
            # 这里必须选择ignore_index=True 或者给 Series 一个index值

            # df = pd.read_csv(file)
            from jqdatasdk import *
            auth('18625801456', 'ZDF173043194zdf')

            end_date = datetime.datetime.strftime(datetime.datetime.now()+datetime.timedelta(days= 1),'%Y-%m-%d')
            df = get_bars('IF2012.CCFX', 61, unit='1m',
                          fields=['date', 'open', 'high', 'low', 'close'],
                          include_now=True, end_dt=None, fq_ref_date=None, df=True)
            print(df)
            close_list = df["close"].values
            close_list = close_list[-61:]
            rsi_list = talib.RSI(close_list, 60)
            # print(rsi_list)
            for i in range(len(rsi_list)):
                if rsi_list[i] >= 55:

                    # print("position:", tradespi.position)
                    Strategy.sell(symbol, df['close'][i], Strategy.fixed_size, df.iloc[[i], [0]])
                    DIRECTION = api.THOST_FTDC_D_Sell

                    result = TradingResult(symbol, 0, df.iloc[[i], [0]], df['close'][i], Strategy.fixed_size, 0, 0, 1)
                    resultList.append(result)
                    print("sell")
                    if(pos <= 0):
                        print("开")
                        sendOrder(tradespi.tapi, BROKERID, EXCHANGEID, INSTRUMENTID, USERID, DIRECTION,
                                            df['close'][len(df)-1], VOLUME, "0",str(OrderRef))
                        OrderRef += 1
                    elif(pos > 0):
                        #平多
                        print("平")
                        sendOrder(tradespi.tapi, BROKERID, EXCHANGEID, INSTRUMENTID, USERID, DIRECTION,
                                            df['close'][len(df)-1], pos, "1", str(OrderRef))
                        OrderRef += 1



                if rsi_list[i] <= 45:
                    Strategy.buy(symbol, df['close'][i], Strategy.fixed_size, df.iloc[[i],[0]])
                    DIRECTION = api.THOST_FTDC_D_Buy
                    result = TradingResult(symbol, df['close'][i], df.iloc[[i],[0]], 0, Strategy.fixed_size, 0, 0, 1)
                    resultList.append(result)
                    print("buy")
                    if (pos >= 0):
                        print("开")
                        sendOrder(tradespi.tapi, BROKERID, EXCHANGEID, INSTRUMENTID, USERID, DIRECTION,
                                            df['close'][len(df)-1], VOLUME, "0", str(OrderRef))
                        OrderRef += 1
                    elif (pos < 0):
                        # 平空
                        print("平")
                        sendOrder(tradespi.tapi, BROKERID, EXCHANGEID, INSTRUMENTID, USERID, DIRECTION,
                                            df['close'][len(df)-1], abs(pos), "1", str(OrderRef))
                        OrderRef += 1
            time.sleep(2)
        if(int(time.time())%60 == 30):
            print("半分钟")
            ReqQryTradingAccountAndPosition(tradeapi, BROKERID, USERID)
            time.sleep(2)

    # 然后基于每笔交易的结果，我们可以计算具体的盈亏曲线和最大回撤等
    capital = 0  # 资金
    maxCapital = 0  # 资金最高净值
    drawdown = 0  # 回撤

    totalResult = 0  # 总成交数量
    totalTurnover = 0  # 总成交金额（合约面值）
    totalCommission = 0  # 总手续费
    totalSlippage = 0  # 总滑点

    timeList = []  # 时间序列
    pnlList = []  # 每笔盈亏序列
    capitalList = []  # 盈亏汇总的时间序列
    drawdownList = []  # 回撤的时间序列

    winningResult = 0  # 盈利次数
    losingResult = 0  # 亏损次数
    totalWinning = 0  # 总盈利金额
    totalLosing = 0  # 总亏损金额

    for result in resultList:
        capital += result.pnl
        maxCapital = max(capital, maxCapital)
        drawdown = capital - maxCapital

        pnlList.append(result.pnl)
        # timeList.append(result.exitDt)  # 交易的时间戳使用平仓时间
        capitalList.append(capital)
        drawdownList.append(drawdown)

        totalResult += 1
        totalTurnover += result.turnover
        totalCommission += result.commission
        totalSlippage += result.slippage

        if result.pnl >= 0:
            winningResult += 1
            totalWinning += result.pnl
        else:
            losingResult += 1
            totalLosing += result.pnl

    # 计算盈亏相关数据
    winningRate = winningResult / totalResult * 100  # 胜率

    averageWinning = 0  # 这里把数据都初始化为0
    averageLosing = 0
    profitLossRatio = 0

    if winningResult:
        averageWinning = totalWinning / winningResult  # 平均每笔盈利
    if losingResult:
        averageLosing = totalLosing / losingResult  # 平均每笔亏损
    if averageLosing:
        profitLossRatio = -totalWinning / totalLosing  # 盈亏比

    # 返回回测结果
    d = {}
    d['capital'] = capital
    d['maxCapital'] = maxCapital
    d['drawdown'] = drawdown
    d['totalResult'] = totalResult
    d['totalTurnover'] = totalTurnover
    d['totalCommission'] = totalCommission
    d['totalSlippage'] = totalSlippage
    d['timeList'] = timeList
    d['pnlList'] = pnlList
    d['capitalList'] = capitalList
    d['drawdownList'] = drawdownList
    d['winningRate'] = winningRate
    d['averageWinning'] = averageWinning
    d['averageLosing'] = averageLosing
    d['profitLossRatio'] = profitLossRatio
    a = [result.__dict__ for result in resultList]
    resultList_pd = pd.DataFrame(a)
    resultList_pd.to_csv('result_list.csv')

    print(Strategy.record_list)
    print(Strategy.pos_information)
    print('ddddddddddd: \n', d)